package com.polimi.meteocal.business.control;

import java.util.Date;
import java.util.Iterator;
import java.util.List;
import javax.annotation.Resource;
import javax.ejb.EJBContext;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import com.polimi.meteocal.business.entity.Event;
import com.polimi.meteocal.business.entity.Notification;
import com.polimi.meteocal.business.entity.User;

/**
 * Session Bean implementation class EventManager
 */
@Stateless
@LocalBean
public class EventManager {
  
	@PersistenceContext
    EntityManager em;
	@Resource
	private EJBContext _context;
	
    public EventManager() {}
    
    /**
     * GET THE LOGGED USER MAIL     
     */
    public String getLoggedUserEmail() {
		return this._context.getCallerPrincipal().getName();
	}
    
    
    public Event getEventById(Integer eventId){
    	return this.em.find(Event.class, eventId);    	
    }
    
    /**
     * STORE EVENT     
     */
    public void saveEvent(Event event,List<String> organizers){ 
    	
    	//SAVE EVENT
    	this.em.persist(event);
    	
    	//SAVE ORGANIZERS
    	setOrganizers(organizers, event);
    	
    	this.em.flush();    	
    }
    
    
    public void setOrganizers(List<String>organizers,Event event){    	
    	organizers.add(getLoggedUserEmail());
    	for(String org : organizers){
    		User user = this.em
				.createNamedQuery(User.FIND_FOR_MAIL, User.class)
				.setParameter("email", org).getSingleResult();
    		user.getEvents().add(event);
    		this.em.persist(user);
    		this.em.flush();
    	} 
    }
    
    /**
     * ADD ORGANIZERS FOR EVERY EVENT   
     */
    private void addOrganizers(List<String> organizersList,Event event){
    	User organizer;
    	for(String org:organizersList){
    		organizer = this.em
        			.createNamedQuery(User.FIND_FOR_MAIL , User.class)
    				.setParameter("email", org).getSingleResult();
    		List<Event> eventOrganized= organizer.getEvents();
    		Iterator<Event> it= eventOrganized.iterator();
    		boolean contains= false;
    		
    		while(it.hasNext()){
    			if(event.getId()==it.next().getId()){
    				contains=true;
    			}
    		}
    		
    		if(!contains)
    			organizer.getEvents().add(event);
    		
    	}
    }
    public void editEvent(Event event,List<String> organizers){
    	addOrganizers(organizers,event);
    	this.em.merge(event);
    	this.em.flush();
    	
    }
    public void deleteEvent(Event event){
    	Event entity = this.em.find(Event.class, event.getId());
		this.em.remove(entity);
		this.em.flush();
		
    }
    public List<Event> getEventsCreated(String user){
    	List<Event> eventsCreated = this.em
				.createNamedQuery(Event.FIND_EVENTS_CREATED, Event.class)
				.setParameter("email", user).getResultList();
    	return eventsCreated;
    }
	
    public Event getEventByNamePlaceDateTime(String name, String place, Date date){
    	Event event=this.em
				.createNamedQuery(Event.FIND_EVENT_FOR_NAME_PLACE_DATETIME, Event.class)
				.setParameter("eventName", name)
				.setParameter("eventPlace", place)
				.setParameter("eventDate", date)
				.getSingleResult();
    	return event;
    }
    /**
     * Get the list of Organizers   
     */
    public List<String> getOrganizersByEvent(Event event){
    	@SuppressWarnings("unchecked")
		List<String> organizers = this.em
    			.createNativeQuery("SELECT USER_MAIL FROM ORGANIZER WHERE EVENT_ID = '"+Integer.toString(event.getId())+"'").getResultList();
    	return organizers;
    }
    /**
     * Get the list of unread Notifications     
     */
    public List<Notification>getUnreadNotifications(String user){
    	List<Notification> unreadNotifications= this.em
				.createNamedQuery(Notification.GET_NOTIFICATIONS, Notification.class)
				.setParameter("user", user).getResultList();
    	return unreadNotifications;
    }
    /**
     * Set the mark for Notification, so it's possible to know if the Notification is read by user     
     */
    public void setNotificationReadMark(List<Notification> readNotification){
    	for(Notification i:readNotification){
    		this.em.merge(i);
    		this.em.flush();
    	}
    }
}
